package ca.camosun.bouncer;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.View;
import ca.camosun.bouncer.components.SensorWrapper;
import ca.camosun.bouncer.components.Tickable;
import ca.camosun.bouncer.game.Paddle;

public class GameActivity extends Activity implements Tickable {

	private static final int SENSOR_TO_PADDLE_SCALER = 2;
	private static final int MINIMUM_Z_TO_BOUNCE = 7;
	private static final int BOUNCE_DELAY = 50;
	private static final int BOUNCE_SCALER = 3;

	private boolean ballIsBouncing;
	private boolean delayOneTick;

	private static int widthPixels;
	private static int heightPixels;

	private Paddle paddle;
	private SensorWrapper sensor;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		DisplayMetrics metrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(metrics);

		widthPixels = metrics.widthPixels;
		heightPixels = metrics.heightPixels;

		setContentView(new GameGridView(this));

		sensor = new SensorWrapper(
				(SensorManager) getSystemService(Context.SENSOR_SERVICE), this);

		ballIsBouncing = false;
		delayOneTick = false;
	}

	@Override
	public void tick(int x, int y, int z) {
		System.out.println("Sensor values: x=" + x + " y=" + y + " z=" + z);

		// Ball not in play.
		if (!paddle.isBallInPlay()) {
			finish();

			System.out.println("Game over - Ball out of bounds.");

			Intent gameOverIntent = new Intent(this, GameOverActivity.class);
			gameOverIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			gameOverIntent.putExtra("score", calculateScore());
			startActivity(gameOverIntent);

			return;
		}

		// Removes jitter when ball lands.
		if (delayOneTick) {
			delayOneTick = false;
			return;
		}

		// Bounce
		if (z > MINIMUM_Z_TO_BOUNCE) {
			ballIsBouncing = true;
			delayOneTick = true;

			int sumX = x * -z * BOUNCE_SCALER;
			int sumY = y * -z * BOUNCE_SCALER;

			Handler landBall = new Handler();

			paddle.attemptBounce(sumX * SENSOR_TO_PADDLE_SCALER, sumY
					* SENSOR_TO_PADDLE_SCALER, z);

			landBall.postDelayed(new Runnable() {
				@Override
				public void run() {
					ballIsBouncing = false;
				}
			}, BOUNCE_DELAY * z);

			return;
		}

		// Roll
		if (!ballIsBouncing) {
			paddle.attemptBounce(x * SENSOR_TO_PADDLE_SCALER, y
					* SENSOR_TO_PADDLE_SCALER, 0);
			return;
		}
	}

	private int calculateScore() {
		return paddle.getTotalAccumulatedHeight();
	}

	@Override
	protected void onResume() {
		super.onResume();

		paddle = new Paddle(widthPixels, heightPixels);

		sensor.startListening();
	}

	@Override
	protected void onPause() {
		super.onPause();

		sensor.stopListening();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	class GameGridView extends View {
		private static final int MINIMUM_BALL_SIZE = 20;
		private static final int ANIMATION_SPEED = 5;

		private int ballSize;
		private int ballX;
		private int ballY;
		
		Paint paint;

		private Bitmap ballBitmap;
		private Rect ballDimensions;

		public GameGridView(Context context) {
			super(context);

			ballSize = MINIMUM_BALL_SIZE;
			ballX = widthPixels / 2;
			ballY = heightPixels / 2;

			paint = new Paint();
			ballDimensions = new Rect();

			Bitmap ballUnscaled = BitmapFactory.decodeResource(getResources(),
					R.drawable.ball);
			ballBitmap = Bitmap.createScaledBitmap(ballUnscaled, ballSize,
					ballSize, true);
		}

		protected void onDraw(Canvas canvas) {
			int targetX = paddle.getBallX();
			int targetY = heightPixels - paddle.getBallY(); // Compensate for
															// conflicting grids

			if (ballIsBouncing) {
				ballSize += ANIMATION_SPEED;

				int xDifference = targetX - ballX;
				int yDifference = targetY - ballY;

				if (ballX != targetX) {
					ballX += xDifference / ANIMATION_SPEED;
				}
				if (ballY != targetY) {
					ballY += yDifference / ANIMATION_SPEED;
				}
			}

			if (!ballIsBouncing) {
				ballX = targetX;
				ballY = targetY;

				if (ballSize > MINIMUM_BALL_SIZE) {
					ballSize -= ANIMATION_SPEED;
				}
			}

			ballDimensions.left = ballX - (ballSize / 2);
			ballDimensions.top = ballY - (ballSize / 2);
			ballDimensions.right = ballDimensions.left + ballSize;
			ballDimensions.bottom = ballDimensions.top + ballSize;

			canvas.drawBitmap(ballBitmap, null, ballDimensions, null);			
			canvas.drawText("Score: " + paddle.getTotalAccumulatedHeight(), 50, 50, paint);
			invalidate();
		}

	}

}